#pragma once
#include <iostream>
#include <string>
#include <sys/msg.h>

template <class T> class MessageManager
{
  public:
    bool Open(std::string path, int id);
    bool Send(long type, T msg);
    bool Receive(long type, T &msg);
    void RemoveMessageQueue();

  private:
    int msgid;
};

template <class T> bool MessageManager<T>::Open(std::string path, int id)
{
    using namespace std;
    key_t key = ftok(path.c_str(), id);
    if (key == -1)
    {
        cerr << "ftok error" << endl;
        return false;
    }

    msgid = msgget(key, IPC_CREAT | 0666);
    if (msgid == -1)
    {
        cerr << "msg creat error" << endl;
        return false;
    }
    return true;
}

template <class T> bool MessageManager<T>::Send(long type, T msg)
{
    struct Message
    {
        long type;
        T msg;
    } msgStruct{type, msg};
    return -1 != msgsnd(msgid, &msgStruct, sizeof(T), IPC_NOWAIT);
}

template <class T> bool MessageManager<T>::Receive(long type, T &msg)
{
    struct Message
    {
        long type;
        T msg;
    } msgStruct;
    int ret = msgrcv(msgid, &msgStruct, sizeof(T), type, IPC_NOWAIT);
    if (ret == -1)
        return false;
    msg = msgStruct.msg;
    return true;
}
template <class T> void MessageManager<T>::RemoveMessageQueue()
{
    msgctl(msgid, IPC_RMID, nullptr);
}